package com.leyou.search.utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.client.ItemClient;
import com.leyou.item.dto.*;
import com.leyou.search.pojo.Goods;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 * <p>
 * 用于吧数据库数据写到elasticsearch
 *
 * @author: wangzibeng
 * Date: 2019/5/6 0006
 * Time: 19:31
 */
@Service
public class ElasticService {
    @Autowired
    private ItemClient itemClient;

    public Goods buildGoods(SpuDTO spu) {
        // 1 商品相关搜索信息的拼接：名称、分类、品牌、规格信息等
        // 1.1 分类名
        String categoryName = itemClient.queryCategoryByIds(spu.getCategoryIds()).stream().map(CategoryDTO::getName).collect(Collectors.joining(","));
        //1.2  品牌
        BrandDTO brandDTO = itemClient.queryBrandById(spu.getBrandId());
        // 1.3 所有名称 完成拼接
        String all = spu.getName() + categoryName + brandDTO.getName();
        // 2   spu下的所有sku的JSON数组
        List<SkuDTO> skuDTOS = itemClient.querySkuBySpuId(spu.getId());
        ArrayList<Map<String, Object>> skuMap = new ArrayList<>();
        for (SkuDTO skuDTO : skuDTOS) {
            HashMap<String, Object> hs = new HashMap<>(4);
            hs.put("title", skuDTO.getTitle());
            hs.put("price", skuDTO.getPrice());
            hs.put("id", skuDTO.getId());
            //截取指定字符串之前的
            hs.put("image", StringUtils.substringBefore(skuDTO.getImages(), ","));
            skuMap.add(hs);
        }
        // 3 当前spu下所有sku的价格的集合
        Set<Long> priceSet = skuDTOS.stream().map(SkuDTO::getPrice).collect(Collectors.toSet());
        // 4 当前spu的规格参数
        // 4.1 获取规格参数的key
        List<SpecParamDTO> specParamDTOS = itemClient.querySpecParams(null, spu.getCid3(), true);
        HashMap<String, Object> specs = new HashMap<>(specParamDTOS.size());
        // 4.2 获取规格参数的值
        SpuDetailDTO spuDetail = itemClient.spuDetailById(spu.getId());
        //4.3 统用参数
        Map<Long, Object> genericSpecMap = JsonUtils.toMap(spuDetail.getGenericSpec(), Long.class, Object.class);
        // 4.4 特有属性
        Map<Long, List<String>> specialSpecMap = JsonUtils.nativeRead(spuDetail.getSpecialSpec(), new TypeReference<Map<Long, List<String>>>() {
        });
        for (SpecParamDTO specParam : specParamDTOS) {
            // 获取规格参数的名称
            String key = specParam.getName();
            // 获取规格参数值
            Object value = null;
            // 判断是否是通用规格
            if (specParam.getGeneric()) {
                // 通用规格
                value = genericSpecMap.get(specParam.getId());
            } else {
                // 特有规格
                value = specialSpecMap.get(specParam.getId());
            }
            // 判断是否是数字类型
            if (specParam.getNumeric()) {
                // 是数字类型，分段
                value = chooseSegment(value, specParam);
            }
            // 添加到specs
            specs.put(key, value);
        }
        Goods goods = new Goods();
        // 从spu对象中拷贝与goods对象中属性名一致的属性
        goods.setBrandId(spu.getBrandId());
        goods.setCategoryId(spu.getCid3());
        goods.setId(spu.getId());
        goods.setSubTitle(spu.getSubTitle());
        goods.setCreateTime(spu.getCreateTime().getTime());
        // spu下的所有sku的JSON数组
        goods.setSkus(JsonUtils.toString(skuMap));
        // 当前spu的规格参数
        goods.setSpecs(specs);
        // 当前spu下所有sku的价格的集合
        goods.setPrice(priceSet);
        // 商品相关搜索信息的拼接：标题、分类、品牌、规格信息等
        goods.setAll(all);
        return goods;
    }

    private String chooseSegment(Object value, SpecParamDTO p) {
        if (value == null || StringUtils.isBlank(value.toString())) {
            return "其它";
        }
        double val = NumberUtils.toDouble(value.toString());
        String result = "其它";
        // 保存数值段
        for (String segment : p.getSegments().split(",")) {
            String[] segs = segment.split("-");
            // 获取数值范围
            double begin = NumberUtils.toDouble(segs[0]);
            double end = Double.MAX_VALUE;
            if (segs.length == 2) {
                end = NumberUtils.toDouble(segs[1]);
            }
            // 判断是否在范围内
            if (val >= begin && val < end) {
                if (segs.length == 1) {
                    result = segs[0] + p.getUnit() + "以上";
                } else if (begin == 0) {
                    result = segs[1] + p.getUnit() + "以下";
                } else {
                    result = segment + p.getUnit();
                }
                break;
            }
        }
        return result;
    }

}
